package com.bjpowernode.shop.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjpowernode.shop.domain.MenuAndAuth;
import com.bjpowernode.shop.domain.SysMenu;
import com.bjpowernode.shop.service.SysMenuService;
import com.bjpowernode.shop.mapper.SysMenuMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author Abai
* @description 针对表【sys_menu(菜单管理)】的数据库操作Service实现
* @createDate 2023-03-28 21:08:51
*/
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu>
    implements SysMenuService{

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Override
    public List<SysMenu> getAllMenuList(String userId) {
        return sysMenuMapper.getAllMenuList(userId);
    }

    @Override
    @Cacheable(cacheNames = "sys:menu:list") 
    public MenuAndAuth getMenuAndAuth() {
        // 通过Security的上下文对象来获取权限信息列表
        Collection<? extends GrantedAuthority> oldAuthorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
        // 转换为普通集合
        List<String> authorities = oldAuthorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());


        // 获取用户id
        String userId = SecurityContextHolder.getContext().getAuthentication().getName();
        // 加载全菜单列表数据
        List<SysMenu> allMenuList = sysMenuMapper.getAllMenuList(userId);

        // 让菜单实体类可有子菜单属性，方便菜单整合父菜单和子菜单
        // 使用递归方法整合父菜单和子菜单
        List<SysMenu> menuList = getMenuAndSubMenu(allMenuList, 0L);

        // 封装权限信息列表和父子菜单列表的结果集
        return MenuAndAuth.builder().authorities(authorities).menuList(menuList).build();
    }

    private List<SysMenu> getMenuAndSubMenu(List<SysMenu> allMenuList, Long parentId) {
        // 从menuList中将父菜单收集起来
        // 从menuList中将当前父菜单的子菜单收集起来
        List<SysMenu> rootMenu = allMenuList.stream().filter(
                // 1.1 、将parentId为0的数据提取出来【提取父菜单】
                // 2.1、将当前父菜单的子菜单提取出来【递归调用后提取的是子菜单或子子...菜单】
                menu -> menu.getParentId().equals(parentId)).collect(Collectors.toList());
        // 1.2、遍历父菜单节点
        // 2.2、遍历子菜单节点
        rootMenu.forEach(root -> {
            // 1.3父菜单节点调用递归方法，回到2.1，获得父菜单对应的子菜单
            // 2.3子菜单节点调用递归方法，回到2.1，但子菜单的id没有对应的子子菜单，所以循环无效
            List<SysMenu> subMenu = getMenuAndSubMenu(
                    // 注：此处仍以全菜单列表做参数，第二参数是父菜单的id
                    allMenuList, root.getMenuId());
            // 封装子菜单数据到当前父菜单节点，为空则跳过
            // 所有父菜单节点遍历完成后，则rootMenu为父(子子子)+父(子子子)+...
            if (!CollectionUtils.isEmpty(subMenu)) root.setList(subMenu);
        });
        // 返回的是整合有父菜单和子菜单的新菜单
        return rootMenu;
    }
}




